home *** CD-ROM | disk | FTP | other *** search
- #include "heightMap.h"
- #include "debug.h"
-
- const DWORD PARTICLE::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
- DWORD FtoDword(float f){return *((DWORD*)&f);}
-
- float Noise(int x)
- {
- x = (x<<13) ^ x;
- return (1.0f - ((x * (x*x * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0f);
- }
-
- float CosInterpolate(float v1, float v2, float a)
- {
- float angle = a * D3DX_PI;
- float prc = (1.0f - cos(angle)) * 0.5f;
- return v1*(1.0f - prc) + v2*prc;
- }
-
- HEIGHTMAP::HEIGHTMAP(IDirect3DDevice9* Dev, INTPOINT _size)
- {
- try
- {
- m_pDevice = Dev;
- m_size = _size;
-
- // Init sprite
- D3DXCreateSprite(m_pDevice,&m_pSprite);
-
- //Reset the heightMap to 0
- m_maxHeight = 15.0f;
- m_pHeightMap = new float[m_size.x * m_size.y];
- memset(m_pHeightMap, 0, sizeof(float) * m_size.x * m_size.y);
-
- //Set particle vertex buffer and texture to NULL
- m_pVb = NULL;
- m_pHeightMapTexture = NULL;
- }
- catch(...)
- {
- debug.Print("Error in HEIGHTMAP::HEIGHTMAP()");
- }
- }
-
- HEIGHTMAP::~HEIGHTMAP()
- {
- Release();
- }
-
- void HEIGHTMAP::Release()
- {
- if(m_pHeightMap != NULL)delete [] m_pHeightMap;
- if(m_pVb != NULL)m_pVb->Release();
- if(m_pSprite != NULL)m_pSprite->Release();
- if(m_pHeightMapTexture != NULL)m_pHeightMapTexture->Release();
- }
-
- HRESULT HEIGHTMAP::LoadFromFile(char fileName[])
- {
- try
- {
- //Reset the heightMap to 0
- memset(m_pHeightMap, 0, sizeof(float) * m_size.x * m_size.y);
-
- //Initiate the texture variables
- if(m_pHeightMapTexture != NULL)m_pHeightMapTexture->Release();
- m_pHeightMapTexture = NULL;
- D3DXIMAGE_INFO info;
-
- //Load the texture (and scale it to our heightMap m_size)
- if(FAILED(D3DXCreateTextureFromFileEx(m_pDevice, fileName, m_size.x, m_size.y, 1, D3DUSAGE_DYNAMIC,
- D3DFMT_L8, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
- NULL, &info, NULL, &m_pHeightMapTexture)))return E_FAIL;
-
- //Lock the texture
- D3DLOCKED_RECT sRect;
- m_pHeightMapTexture->LockRect(0, &sRect, NULL, NULL);
- BYTE *bytes = (BYTE*)sRect.pBits;
-
- //Extract height values from the texture
- for(int y=0;y<m_size.y;y++)
- for(int x=0;x<m_size.x;x++)
- {
- BYTE *b = bytes + y * sRect.Pitch + x;
- m_pHeightMap[x + y * m_size.x] = ((float)*b / 255.0f) * m_maxHeight;
- }
-
- //Unlock the texture
- m_pHeightMapTexture->UnlockRect(0);
- }
- catch(...)
- {
- debug.Print("Error in HEIGHTMAP::LoadFromFile()");
- }
-
- return S_OK;
- }
-
- HRESULT HEIGHTMAP::CreateRandomHeightMap(int seed, float noiseSize, float persistence, int octaves)
- {
- if(m_pHeightMapTexture != NULL){m_pHeightMapTexture->Release(); m_pHeightMapTexture = NULL;}
- m_pDevice->CreateTexture(m_size.x, m_size.y, 1, D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, &m_pHeightMapTexture, NULL);
-
- D3DLOCKED_RECT lock;
- m_pHeightMapTexture->LockRect(0, &lock, NULL, NULL);
-
- //For each map node
- for(int y=0;y<m_size.y;y++)
- for(int x=0;x<m_size.x;x++)
- {
- //Scale x & y to the range of 0.0 - m_size
- float xf = ((float)x / (float)m_size.x) * noiseSize;
- float yf = ((float)y / (float)m_size.y) * noiseSize;
-
- float total = 0;
-
- // For each octave
- for(int i=0;i<octaves;i++)
- {
- //Calculate frequency and amplitude (different for each octave)
- float freq = pow(2, i);
- float amp = pow(persistence, i);
-
- //Calculate the x,y noise coordinates
- float tx = xf * freq;
- float ty = yf * freq;
- int tx_int = tx;
- int ty_int = ty;
-
- //Calculate the fractions of x & y
- float fracX = tx - tx_int;
- float fracY = ty - ty_int;
-
- //Get the noise of this octave for each of these 4 points
- float v1 = Noise(tx_int + ty_int * 57 + seed);
- float v2 = Noise(tx_int+ 1 + ty_int * 57 + seed);
- float v3 = Noise(tx_int + (ty_int+1) * 57 + seed);
- float v4 = Noise(tx_int + 1 + (ty_int+1) * 57 + seed);
-
- //Smooth in the X-axis
- float i1 = CosInterpolate(v1 , v2 , fracX);
- float i2 = CosInterpolate(v3 , v4 , fracX);
-
- //Smooth in the Y-axis
- total += CosInterpolate(i1 , i2 , fracY) * amp;
- }
-
- int b = 128 + total * 128.0f;
- if(b < 0)b = 0;
- if(b > 255)b = 255;
-
- BYTE *bDest = (BYTE*)lock.pBits;
- bDest += y * lock.Pitch + x;
- *bDest = b;
-
- //Save to heightMap
- m_pHeightMap[x + y * m_size.x] = ((float)b / 255.0f) * m_maxHeight;
- }
-
- m_pHeightMapTexture->UnlockRect(0);
-
- return S_OK;
- }
-
- HRESULT HEIGHTMAP::CreateParticles()
- {
- try
- {
- if(m_pVb != NULL)
- {
- m_pVb->Release();
- m_pVb = NULL;
- }
-
- if(FAILED(m_pDevice->CreateVertexBuffer(m_size.x * m_size.y * sizeof(PARTICLE), D3DUSAGE_DYNAMIC | D3DUSAGE_POINTS | D3DUSAGE_WRITEONLY, PARTICLE::FVF, D3DPOOL_DEFAULT, &m_pVb, 0)))
- debug.Print("Failed to create particle vertex buffer");
-
- PARTICLE *v = NULL;
- m_pVb->Lock(0, 0, (void**)&v, D3DLOCK_DISCARD);
-
- for(int y=0;y<m_size.y;y++)
- for(int x=0;x<m_size.x;x++)
- {
- float prc = m_pHeightMap[x + y * m_size.x] / m_maxHeight;
- int red = 255 * prc;
- int green = 255 * (1.0f - prc);
-
- v->color = D3DCOLOR_ARGB(255, red, green, 0);
- v->position = D3DXVECTOR3(x, m_pHeightMap[x + y * m_size.x], -y);
- v++;
- }
-
- m_pVb->Unlock();
-
- }
- catch(...)
- {
- debug.Print("Error in HEIGHTMAP::CreateParticles()");
- return E_FAIL;
- }
-
- return S_OK;
- }
-
- void HEIGHTMAP::Render()
- {
- try
- {
- if(m_pVb != NULL)
- {
- m_pDevice->SetRenderState(D3DRS_LIGHTING, false);
- m_pDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, true);
- m_pDevice->SetRenderState(D3DRS_POINTSCALEENABLE, true);
-
- m_pDevice->SetRenderState(D3DRS_POINTSIZE, FtoDword(0.7f));
- m_pDevice->SetRenderState(D3DRS_POINTSIZE_MIN, FtoDword(0.0f));
- m_pDevice->SetRenderState(D3DRS_POINTSCALE_A, 0);
- m_pDevice->SetRenderState(D3DRS_POINTSCALE_B, FtoDword(0.0f));
- m_pDevice->SetRenderState(D3DRS_POINTSCALE_C, FtoDword(1.0f));
- m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, false);
-
- m_pDevice->SetTexture(0, NULL);
- m_pDevice->SetFVF(PARTICLE::FVF);
- m_pDevice->SetStreamSource(0, m_pVb, 0, sizeof(PARTICLE));
- m_pDevice->DrawPrimitive(D3DPT_POINTLIST, 0, m_size.x * m_size.y);
- }
-
- if(m_pSprite != NULL)
- {
- m_pSprite->Begin(0);
- m_pSprite->Draw(m_pHeightMapTexture, NULL, NULL, &D3DXVECTOR3(1.0f, 1.0f, 1.0f), 0xffffffff);
- m_pSprite->End();
- }
- }
- catch(...)
- {
- debug.Print("Error in HEIGHTMAP::Render()");
- }
- }